// Copyright (c) Lawrence Livermore National Security, LLC and other VisIt
// Project developers.  See the top-level LICENSE file for dates and other
// details.  No copyright assignment is required to contribute to VisIt.

// ****************************************************************************
//  File: CurveViewerEnginePluginInfo.C
// ****************************************************************************

#include <CurvePluginInfo.h>
#include <avtCurvePlot.h>
#include <CurveAttributes.h>

//
// Storage for static data elements.
//
CurveAttributes *CurveViewerEnginePluginInfo::clientAtts = NULL;
CurveAttributes *CurveViewerEnginePluginInfo::defaultAtts = NULL;

// ****************************************************************************
//  Method:  CurveViewerEnginePluginInfo::InitializeGlobalObjects
//
//  Purpose:
//    Initialize the plot atts.
//
//  Programmer: generated by xml2info
//  Creation:   omitted
//
// ****************************************************************************
void
CurveViewerEnginePluginInfo::InitializeGlobalObjects()
{
    if (CurveViewerEnginePluginInfo::clientAtts == NULL)
    {
        CurveViewerEnginePluginInfo::clientAtts  = new CurveAttributes;
        CurveViewerEnginePluginInfo::defaultAtts = new CurveAttributes;
    }
}

// ****************************************************************************
//  Method: CurveViewerEnginePluginInfo::GetClientAtts
//
//  Purpose:
//    Return a pointer to the viewer client attributes.
//
//  Returns:    A pointer to the viewer client attributes.
//
//  Programmer: generated by xml2info
//  Creation:   omitted
//
// ****************************************************************************

AttributeSubject *
CurveViewerEnginePluginInfo::GetClientAtts()
{
    return clientAtts;
}

// ****************************************************************************
//  Method: CurveViewerEnginePluginInfo::GetDefaultAtts
//
//  Purpose:
//    Return a pointer to the viewer default attributes.
//
//  Returns:    A pointer to the viewer default attributes.
//
//  Programmer: generated by xml2info
//  Creation:   omitted
//
// ****************************************************************************

AttributeSubject *
CurveViewerEnginePluginInfo::GetDefaultAtts()
{
    return defaultAtts;
}

// ****************************************************************************
//  Method: CurveViewerEnginePluginInfo::SetClientAtts
//
//  Purpose:
//    Set the viewer client attributes.
//
//  Arguments:
//    atts      A pointer to the new client attributes.
//
//  Programmer: generated by xml2info
//  Creation:   omitted
//
// ****************************************************************************

void
CurveViewerEnginePluginInfo::SetClientAtts(AttributeSubject *atts)
{
    *clientAtts = *(CurveAttributes *)atts;
    clientAtts->Notify();
}

// ****************************************************************************
//  Method: CurveViewerEnginePluginInfo::GetClientAtts
//
//  Purpose:
//    Get the viewer client attributes.
//
//  Arguments:
//    atts      A pointer to return the client default attributes in.
//
//  Programmer: generated by xml2info
//  Creation:   omitted
//
// ****************************************************************************

void
CurveViewerEnginePluginInfo::GetClientAtts(AttributeSubject *atts)
{
    *(CurveAttributes *)atts = *clientAtts;
}

// ****************************************************************************
//  Method: CurveViewerEnginePluginInfo::AllocAvtPlot
//
//  Purpose:
//    Return a pointer to a newly allocated avt plot.
//
//  Returns:    A pointer to the newly allocated avt plot.
//
//  Programmer: generated by xml2info
//  Creation:   omitted
//
// ****************************************************************************

avtPlot *
CurveViewerEnginePluginInfo::AllocAvtPlot()
{
    return new avtCurvePlot;
}

bool
CurveViewerEnginePluginInfo::PermitsCurveViewScaling() const
{
    return true;
}

// ****************************************************************************
//  Method: CurveViewerEnginePluginInfo::InitializePlotAtts
//
//  Purpose:
//    Initialize the plot attributes to the default attributes.
//
//  Arguments:
//    atts      The attribute subject to initialize.
//    md        The metadata used to initialize.
//    atts      The variable name used to initialize.
//
//  Programmer: whitlocb -- generated by xml2info
//  Creation:   Fri Mar 26 15:09:32 PST 2004
//
//  Modifications:
//    Kathleen Bonnell, Mon Oct 31 17:05:35 PST 2005
//    Added call to SetColor.
//
//    Mark C. Miller, Mon Nov  2 11:53:01 PST 2020
//    Changed name of SetColor to SetAutonomousColors
// ****************************************************************************
#include <avtPlotMetaData.h>

void
CurveViewerEnginePluginInfo::InitializePlotAtts(AttributeSubject *atts,
    const avtPlotMetaData &plot)
{
    *(CurveAttributes*)atts = *defaultAtts;
    SetAutonomousColors(atts,
        plot.GetBackgroundColor(), plot.GetForegroundColor());
}

// ****************************************************************************
// Method: CurveViewerEnginePluginInfo::SupportsAnimation
//
// Purpose:
//   Tell VisIt that this plot supports animation.
//
// Programmer: Brad Whitlock
// Creation:   Fri Sep 13 11:29:59 PDT 2013
//
// Modifications:
//
// ****************************************************************************

bool
CurveViewerEnginePluginInfo::SupportsAnimation() const
{
    return true;
}

// ****************************************************************************
// Method: CurveViewerEnginePluginInfo::AnimationReset
//
// Purpose:
//   Resets the plot's animation.
//
// Arguments:
//   atts : The attribute subject that we may modify.
//   plot : The plot that we're animating.
//
// Returns:  True if the plot attributes changed as a result of reset.
//
// Programmer: Brad Whitlock
// Creation:   Fri Sep 13 11:29:59 PDT 2013
//
// Modifications:
//
// ****************************************************************************

bool
CurveViewerEnginePluginInfo::AnimationReset(AttributeSubject *atts, const avtPlotMetaData &plot)
{
    CurveAttributes *cAtts = (CurveAttributes *)atts;
    bool update = false;
    if(cAtts->GetDoBallTimeCue() || cAtts->GetDoLineTimeCue())
    {
        if(plot.GetActualSpatialExtents().HasExtents())
        {
            double ext[6] = {0., 1., 0., 1., 0., 1.};
            plot.GetActualSpatialExtents().CopyTo(ext);

            cAtts->SetTimeForTimeCue(ext[0]);
            update = true;
        }
    }
    return update;
}

// ****************************************************************************
// Method: CurveViewerEnginePluginInfo::AnimationStep
//
// Purpose:
//   Take an animation step.
//
// Arguments:
//   atts : The attribute subject that we may modify.
//   plot : The plot that we're animating.
//
// Returns:  True if the plot attributes changed.
//
// Programmer: Brad Whitlock
// Creation:   Fri Sep 13 11:29:59 PDT 2013
//
// Modifications:
//
// ****************************************************************************

bool
CurveViewerEnginePluginInfo::AnimationStep(AttributeSubject *atts, const avtPlotMetaData &plot)
{
    CurveAttributes *cAtts = (CurveAttributes *)atts;
    bool update = false;
    if(cAtts->GetDoBallTimeCue() || cAtts->GetDoLineTimeCue())
    {
        if(plot.GetActualSpatialExtents().HasExtents())
        {
            double ext[6] = {0., 1., 0., 1., 0., 1.};
            plot.GetActualSpatialExtents().CopyTo(ext);

            double EPS = (ext[1] - ext[0]) / 1000.;
            double currentT = cAtts->GetTimeForTimeCue();
            if(currentT >= ext[0]-EPS && currentT <= ext[1]+EPS)
            {
                double t = (currentT - ext[0]) / (ext[1] - ext[0]);
                t += 0.01;
                double newT = (1. - t) * ext[0] + t * ext[1];
                if(newT > ext[1])
                    cAtts->SetTimeForTimeCue(ext[0]);
                else
                    cAtts->SetTimeForTimeCue(newT);
            }
            else
                cAtts->SetTimeForTimeCue(ext[0]);
            update = true;
        }
    }
    return update;
}

// ****************************************************************************
//  Method: CurveViewerEnginePluginInfo::GetMenuName
//
//  Purpose:
//    Return a pointer to the name to use in the viewer menus.
//
//  Returns:    A pointer to the name to use in the viewer menus.
//
//  Programmer: generated by xml2info
//  Creation:   omitted
//
// ****************************************************************************

const char *
CurveViewerEnginePluginInfo::GetMenuName() const
{
    return "Curve";
}

// ****************************************************************************
//  Method: CurveViewerEnginePluginInfo::SetAutonomousColors
//
//  Purpose:
//    Sets the color if the CycleColors att is set to true. 
//
//  Arguments:
//    atts      The attribute subject. 
//
//  Programmer: Kathleen Bonnell 
//  Creation:   October 31, 2005 
//
//  Modifications:
//
//    Hank Childs, Sat Mar 13 10:35:34 PST 2010
//    Change Boolean test to comparison with enumeration.
//
//    Brad Whitlock, Fri Jul  5 16:55:22 PDT 2013
//    Set the fill color too.
//
//    Mark C. Miller, Mon Nov  2 17:54:17 PST 2020
//    Changed name to SetAutonomousColors where any modes for selecting
//    color that do not involve the user specifying an explicit color are
//    handled here.
// ****************************************************************************
#include <avtColorTables.h>

void
CurveViewerEnginePluginInfo::SetAutonomousColors(AttributeSubject *atts,
    double const *bgColor, double const *fgColor)
{
    CurveAttributes *curveAtts = (CurveAttributes *)atts;

    if (curveAtts->GetCurveColorSource() == CurveAttributes::Cycle)
    {
        unsigned char bg[3] = {static_cast<unsigned char>(bgColor[0]*255),
                               static_cast<unsigned char>(bgColor[1]*255),
                               static_cast<unsigned char>(bgColor[2]*255)};
        unsigned char rgb[3] = {static_cast<unsigned char>(fgColor[0]*255),
                                static_cast<unsigned char>(fgColor[1]*255),
                                static_cast<unsigned char>(fgColor[2]*255)};
        avtColorTables *ct = avtColorTables::Instance();

        if (!ct->GetJNDControlPointColor(ct->GetDefaultDiscreteColorTable(),
                                            "CurveColor", bg, rgb))
            ct->GetJNDControlPointColor("distinct", "CurveColor" , bg, rgb);

        ColorAttribute c(rgb[0], rgb[1], rgb[2]);
        curveAtts->SetCurveColor(c);
        curveAtts->SetFillColor1(c);

        // Make a whiter version of the color for fill color 2.
        unsigned char wrgb[3];
        avtColorTables::ModifyColor(rgb, 1.75, wrgb);
        ColorAttribute wc(wrgb[0], wrgb[1], wrgb[2]);
        curveAtts->SetFillColor2(wc);

        // Inform GUI of color selections made here
        SetClientAtts(atts);
    }
}

